/* Assembler macros for x86-64.
   Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA.  */

#ifdef __ASSEMBLER__

/* Syntactic details of assembler.  */

#ifdef HAVE_ELF

/* ELF uses byte-counts for .align, most others use log2 of count of bytes.  */
#define ALIGNARG(log2) (1 << (log2))
/* For ELF we need the `.type' directive to make shared libs work right.  */
#define ASM_TYPE_DIRECTIVE(name, typearg) .type name,typearg;
#define ASM_SIZE_DIRECTIVE(name)          .size name,.-name;

/* In ELF C symbols are asm symbols.  */
#undef NO_UNDERSCORES
#define NO_UNDERSCORES

#else

#define ALIGNARG(log2)                 log2
#define ASM_TYPE_DIRECTIVE(name, type) /* Nothing is specified.  */
#define ASM_SIZE_DIRECTIVE(name)       /* Nothing is specified.  */

#endif

/* Define an entry point visible from C.  */
#define ENTRY(name)                                     \
    ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name);           \
    ASM_TYPE_DIRECTIVE(C_SYMBOL_NAME(name), @function); \
    .align ALIGNARG(4);                                 \
    C_LABEL(name)                                       \
    cfi_startproc;                                      \
    CALL_MCOUNT

#undef END
#define END(name) \
    cfi_endproc;  \
    ASM_SIZE_DIRECTIVE(name)

/* If compiled for profiling, call `mcount' at the start of each function.  */
#ifdef PROF
/* The mcount code relies on a normal frame pointer being on the stack
   to locate our caller, so push one just for its benefit.  */
#define CALL_MCOUNT              \
    pushq %rbp;                  \
    cfi_adjust_cfa_offset(8);    \
    movq %rsp, %rbp;             \
    cfi_def_cfa_register(%rbp);  \
    call JUMPTARGET(mcount);     \
    popq %rbp;                   \
    cfi_def_cfa(rsp, 8);
#else
#define CALL_MCOUNT /* Do nothing.  */
#endif

#ifdef NO_UNDERSCORES
/* Since C identifiers are not normally prefixed with an underscore
   on this system, the asm identifier `syscall_error' intrudes on the
   C name space.  Make sure we use an innocuous name.  */
#define syscall_error __syscall_error
#define mcount        _mcount
#endif

// commented by GP
#define PSEUDO(name, syscall_name, args) \
    lose:                                \
    jmp JUMPTARGET(syscall_error);       \
    .globl syscall_error;                \
    ENTRY(name)                          \
    DO_CALL(syscall_name, args);         \
    jb lose

#undef PSEUDO_END
#define PSEUDO_END(name) END(name)

#undef JUMPTARGET
#ifdef PIC
#define JUMPTARGET(name) name##@PLT
#else
#define JUMPTARGET(name) name
#endif

/* Local label name for asm code. */
#ifndef L
#ifdef HAVE_ELF
/* ELF-like local names start with `.L'.  */
#define L(name) .L##name
#else
#define L(name) name
#endif
#endif

#endif /* __ASSEMBLER__ */
